﻿Imports System.Data.OleDb

' Generische Implementation von Manager
Public MustInherit Class ManagerImpl(Of T As Base)
    Implements Manager(Of T)

    Protected tableName As String

    Protected defaultRowMapper As RowMapper(Of T)

    Public Sub New(ByRef tableName As String, ByRef defaultRowMapper As RowMapper(Of T))
        Me.tableName = tableName
        Me.defaultRowMapper = defaultRowMapper
    End Sub

    Public Function findById(ByRef entity As T) As T Implements Manager(Of T).findById
        Dim query As New SelectByIdQuery(tableName, entity.id)
        Return selectSingleQuery(query, defaultRowMapper)
    End Function

    Public Function findAll() As List(Of T) Implements Manager(Of T).findAll
        Dim query As New SelectAllQuery(tableName)
        Return selectQuery(query, defaultRowMapper)
    End Function

    Public Sub save(ByRef entity As T) Implements Manager(Of T).save
        If entity.id = 0 Then
            Connection.beginTransaction()
            insert(entity)
            entity.id = findLatestId()
            Connection.commitTransatcion()
        Else
            update(entity)
        End If
    End Sub

    Public MustOverride Sub update(ByRef entity As T)

    Public MustOverride Sub insert(ByRef entity As T)

    Public Function findLatestId() As Long
        Dim query As New Query()
        query.sql = "select max(id) as max_id from " & tableName
        Return selectSingleQuery(Of DummyBase)(query, New MaxIdMapper()).id
    End Function

    Public Sub delete(ByRef entity As T) Implements Manager(Of T).delete
        Dim query As New DeleteQuery(tableName, entity.id)
        runQuery(query)
    End Sub

    ' run query without answer (i.e. insert, update, delete)
    Public Sub runQuery(ByRef query As Query)
        Connection.executeNonQuery(query)
    End Sub

    ' run query with a list of result
    Public Function selectQuery(ByRef query As Query, ByRef mapper As RowMapper(Of T)) As List(Of T)
        Dim reader As OleDbDataReader = Connection.executeReader(query)
        Dim result As New List(Of T)
        Do While reader.Read()
            result.Add(mapper.map(reader))
        Loop
        Return result
    End Function

    ' run query with a single result
    Public Function selectSingleQuery(Of TT As Base)(ByRef query As Query, ByRef mapper As RowMapper(Of TT)) As TT
        Dim reader As OleDbDataReader = Connection.executeReader(query)
        If reader.HasRows Then
            reader.Read()
            Return mapper.map(reader)
        Else
            Return Nothing
        End If
    End Function
End Class
